﻿Imports System.Net
Imports System.Net.NetworkInformation
Imports System.Timers
Imports System.Threading
Imports System.Data.SqlClient
Imports System.Collections.ObjectModel

Delegate Sub TimerCallBack()

Public Class KelControl

#Region "Champs"
    'Liste des données
    Private listSitesWeb As New Collection()
    Private listServeurs As New Collection()
    Private listWebServices As New Collection()

    'Liste des anciennes données erroné
    Private listErrSitesWeb As New Collection(Of dataReportSites)
    Private listErrServeurs As New Collection(Of dataReportServeurs)
    Private listErrWebServices As New Collection(Of dataReportServices)

    'Configuration des timers
    Private sysConfig As dataConfiguration

    'Les 3 timers distincts 
    Private timerSitesWeb As System.Timers.Timer
    Private timerServeurs As System.Timers.Timer
    Private timerWebServices As System.Timers.Timer

    'Les 3 thread distincts
    Private threadSitesWeb As Thread
    Private threadServeurs As Thread
    Private threadWebServices As Thread

    'Les 3 timers de post traitement
    Private cbStartSiteWeb As TimerCallBack
    Private cbStartServeurs As TimerCallBack
    Private cbStartWebServices As TimerCallBack

    'Les 3 timers de pré traitement
    Private cbEndSiteWeb As TimerCallBack
    Private cbEndServeurs As TimerCallBack
    Private cbEndWebServices As TimerCallBack

    'Variables des données (SGBD)
    Private sConnexion As String = "Data Source=POSTE-DEV16;Initial Catalog=KelControl;User ID=sa;Password=kelstage"
    Private sqlConnexion(3) As SqlConnection
    Private scConnexion As SqlCommand
    Private dataConnexion As New SqlDataAdapter
    Private dataReadConnexion As SqlDataReader
    Private dsConnexion As New DataSet
#End Region

#Region "Propriétés"
    Public Property cbOnStartSiteWeb As [Delegate]
        Set(ByVal value As [Delegate])
            cbStartSiteWeb = value
        End Set
        Get
            Return cbStartSiteWeb
        End Get
    End Property

    Public Property cbOnEndSiteWeb As [Delegate]
        Set(ByVal value As [Delegate])
            cbEndSiteWeb = value
        End Set
        Get
            Return cbEndSiteWeb
        End Get
    End Property

    Public Property cbOnStartServeurs As [Delegate]
        Set(ByVal value As [Delegate])
            cbStartServeurs = value
        End Set
        Get
            Return cbStartServeurs
        End Get
    End Property

    Public Property cbOnEndServeurs As [Delegate]
        Set(ByVal value As [Delegate])
            cbEndServeurs = value
        End Set
        Get
            Return cbEndServeurs
        End Get
    End Property

    Public Property cbOnStartWebServices As [Delegate]
        Set(ByVal value As [Delegate])
            cbStartWebServices = value
        End Set
        Get
            Return cbStartWebServices
        End Get
    End Property

    Public Property cbOnEndWebServices As [Delegate]
        Set(ByVal value As [Delegate])
            cbEndWebServices = value
        End Set
        Get
            Return cbEndWebServices
        End Get
    End Property

    Public ReadOnly Property itServeurs As Integer
        Get
            Return Me.sysConfig.iTimerServeurs / 60000
        End Get
    End Property

    Public ReadOnly Property itServices As Integer
        Get
            Return Me.sysConfig.iTimerServices / 60000
        End Get
    End Property

    Public ReadOnly Property itSitesWeb As Integer
        Get
            Return Me.sysConfig.iTimerSites / 60000
        End Get
    End Property
#End Region

#Region "Configuration"
    Public Sub New()
        Try
            Dim ping As Ping = New Ping()
            Dim reponse As PingReply = ping.Send("www.google.fr")

            If Not reponse.Status = IPStatus.Success Then
                Throw New PingException("")
            End If

            sqlConnexion(0) = New SqlConnection()
            sqlConnexion(0).ConnectionString = sConnexion
            sqlConnexion(0).Open()
            recupererConfiguration()
            sqlConnexion(0).Dispose()
            sqlConnexion(0).Close()
        Catch ex As PingException
            Throw New Exception("Connexion Internet requise")
        Catch ex As SqlException
            Throw New Exception("Impossible de se connecter au serveur de base de donnée")
        End Try
    End Sub

    Public Sub arret()
        'Attente de la fin des traitements des threads
        'threadSitesWeb.Join()
        'threadServeurs.Join()
        'threadWebServices.Join()

        'Arret des timers
        timerSitesWeb.Dispose()
        timerServeurs.Dispose()
        timerWebServices.Dispose()
    End Sub

    Public Sub initAllThread()
        startThreadSiteWeb()
        startThreadServeurs()
        startThreadWebServices()
    End Sub

    Private Sub recupererConfiguration()
        Dim sRequete = "SELECT sites_timer, sites_erreurReport, serveurs_timer, serveurs_erreurReport, " & _
                       "services_timer, services_erreurReport FROM Config_system"
        Dim row As Object() = Nothing

        scConnexion = New SqlCommand(sRequete, sqlConnexion(0))
        dataReadConnexion = scConnexion.ExecuteReader

        While dataReadConnexion.Read
            If row Is Nothing Then
                row = New Object(dataReadConnexion.FieldCount) {}
            End If
            dataReadConnexion.GetValues(row)
            sysConfig.iTimerSites = row(0) * 60000
            sysConfig.iNbErreurSites = row(1)
            sysConfig.iTimerServeurs = row(2) * 60000
            sysConfig.iNbErreurServeurs = row(3)
            sysConfig.iTimerServices = row(4) * 60000
            sysConfig.iNbErreurServices = row(5)
        End While
        dataReadConnexion.Dispose()
    End Sub
#End Region

#Region "Site Web"
    Private Sub recupererListeSiteWeb()
        Dim sRequete = "SELECT url FROM Config_sites"
        Dim row As Object() = Nothing
        listSitesWeb.Clear()

        scConnexion = New SqlCommand(sRequete, sqlConnexion(0))
        dataReadConnexion = scConnexion.ExecuteReader

        While dataReadConnexion.Read
            If row Is Nothing Then
                row = New Object(dataReadConnexion.FieldCount) {}
            End If
            dataReadConnexion.GetValues(row)
            For i = 0 To row.GetLength(0) - 1
                If Not row(i) Is Nothing AndAlso Not (row(i) Is DBNull.Value) Then
                    Dim data = Trim(row(i).ToString)
                    listSitesWeb.Add(data)
                End If
            Next
        End While
        dataReadConnexion.Dispose()
    End Sub

    Public Sub startThreadSiteWeb()
        threadSitesWeb = New Thread(AddressOf initTimerSiteWeb)
        threadSitesWeb.Start()
    End Sub

    Private Sub initTimerSiteWeb()
        Try
            timerSitesWeb = New System.Timers.Timer(sysConfig.iTimerSites)
            If (cbStartSiteWeb <> Nothing) Then
                AddHandler timerSitesWeb.Elapsed, Sub(sender, e) cbStartSiteWeb()
            End If
            AddHandler timerSitesWeb.Elapsed, AddressOf cbTimerSiteWeb
            If (cbEndSiteWeb <> Nothing) Then
                AddHandler timerSitesWeb.Elapsed, Sub(sender, e) cbEndSiteWeb()
            End If

            If (cbStartSiteWeb <> Nothing) Then
                cbStartSiteWeb()
            End If
            cbTimerSiteWeb(Nothing, Nothing)
            If (cbEndSiteWeb <> Nothing) Then
                cbEndSiteWeb()
            End If
        Catch ex As Exception
            Dim err = ex.Message
        End Try
    End Sub

    Private Sub cbTimerSiteWeb(ByVal source As Object, ByVal e As ElapsedEventArgs)
        timerSitesWeb.Stop()
        sqlConnexion(0) = New SqlConnection()
        sqlConnexion(0).ConnectionString = sConnexion
        sqlConnexion(0).Open()

        Dim origin As New Date(1970, 1, 1)
        Dim span As TimeSpan = Now - origin
        Dim idPassage As Long = Math.Ceiling(span.TotalSeconds)

        recupererListeSiteWeb()

        For Each url As String In listSitesWeb
            Dim oSiteData As New dataReportSites()
            oSiteData.uSiteUrl = New Uri(url)
            oSiteData.dVerificationDate = Now
            oSiteData.sVerificationStatut = enStatutVerifications.Aucune
            oSiteData.sMessageErreur = String.Empty
            envoiRequeteHTTP(oSiteData)
            reportSitesWeb(idPassage, oSiteData)
        Next
        sqlConnexion(0).Dispose()
        sqlConnexion(0).Close()
        timerSitesWeb.Start()
    End Sub

    Private Sub envoiRequeteHTTP(ByRef oSiteData As dataReportSites)
        Try
            Dim requette As HttpWebRequest = WebRequest.Create(oSiteData.uSiteUrl)
            Dim reponse As HttpWebResponse = requette.GetResponse()

            If (Not reponse.StatusCode = HttpStatusCode.OK) Then
                Select Case reponse.StatusCode
                    Case HttpStatusCode.Accepted, _
                         HttpStatusCode.PartialContent
                        oSiteData.sVerificationStatut = enStatutVerifications.ErreurMineur
                        oSiteData.sMessageErreur = reponse.StatusCode
                    Case HttpStatusCode.NotFound, _
                         HttpStatusCode.InternalServerError, _
                         HttpStatusCode.NotImplemented, _
                         HttpStatusCode.BadGateway, _
                         HttpStatusCode.ServiceUnavailable, _
                         HttpStatusCode.GatewayTimeout, _
                         HttpStatusCode.HttpVersionNotSupported
                        oSiteData.sVerificationStatut = enStatutVerifications.ReverificationRequise
                        oSiteData.sMessageErreur = reponse.StatusCode
                    Case 507
                        oSiteData.sVerificationStatut = enStatutVerifications.ReverificationRequise
                        oSiteData.sMessageErreur = reponse.StatusCode
                    Case 509
                        oSiteData.sVerificationStatut = enStatutVerifications.ReverificationRequise
                        oSiteData.sMessageErreur = reponse.StatusCode
                    Case Else
                        oSiteData.sVerificationStatut = enStatutVerifications.Aucune
                        oSiteData.sMessageErreur = reponse.StatusCode
                End Select
            End If
        Catch ex As Exception
            oSiteData.sVerificationStatut = enStatutVerifications.ReverificationRequise
            oSiteData.sMessageErreur = ex.Message
        End Try
    End Sub

    Private Sub reportSitesWeb(ByVal idPassage As Long, ByVal oSiteData As dataReportSites)
        Try
            If (Not oSiteData.sMessageErreur = String.Empty) Then
                If (oSiteData.sVerificationStatut = enStatutVerifications.ReverificationRequise) Then
                    oSiteData.iErreurCount = 1
                    If (listErrSitesWeb.Count = 0) Then
                        listErrSitesWeb.Add(oSiteData)
                    Else
                        For i = 0 To listErrSitesWeb.Count - 1 Step 1
                            If (listErrSitesWeb(i).uSiteUrl = oSiteData.uSiteUrl) Then
                                If (listErrSitesWeb(i).sMessageErreur = oSiteData.sMessageErreur) Then
                                    oSiteData.iErreurCount = listErrSitesWeb(i).iErreurCount + 1
                                    listErrSitesWeb(i) = oSiteData
                                End If
                                If (oSiteData.iErreurCount >= sysConfig.iNbErreurSites) Then
                                    oSiteData.sVerificationStatut = enStatutVerifications.ErreurMajeur
                                End If
                            ElseIf i = listErrSitesWeb.Count - 1 Then
                                listErrSitesWeb.Add(oSiteData)
                            End If
                        Next
                    End If
                End If
            Else
                For i = 0 To listErrSitesWeb.Count - 1 Step 1
                    If (listErrSitesWeb(i).uSiteUrl = oSiteData.uSiteUrl) Then
                        listErrSitesWeb.RemoveAt(i)
                    End If
                Next
            End If

            Dim sRequete = "INSERT INTO Rapport_sites (url,date,idPassage,statut,message,nbErreur) VALUES ('" _
                            & oSiteData.uSiteUrl.ToString & "', '" _
                            & oSiteData.dVerificationDate.ToString & "', '" _
                            & idPassage.ToString & "', '" _
                            & oSiteData.sVerificationStatut.ToString & "', '" _
                            & Replace(oSiteData.sMessageErreur.ToString, "'", """") & "', " _
                            & oSiteData.iErreurCount & ")"
            scConnexion = New SqlCommand(sRequete, sqlConnexion(0))
            dataConnexion.SelectCommand = scConnexion
            dataConnexion.Fill(dsConnexion)
            dataConnexion.Dispose()
        Catch ex As SqlException
            Dim test = ex.Message
        End Try
    End Sub
#End Region

#Region "Serveurs"
    Private Sub recupererListeServeurs()
        Dim sRequete = "SELECT ip FROM Config_serveurs"
        Dim row As Object() = Nothing
        listServeurs.Clear()

        scConnexion = New SqlCommand(sRequete, sqlConnexion(1))
        dataReadConnexion = scConnexion.ExecuteReader

        While dataReadConnexion.Read
            If row Is Nothing Then
                row = New Object(dataReadConnexion.FieldCount) {}
            End If
            dataReadConnexion.GetValues(row)
            For i = 0 To row.GetLength(0) - 1
                If Not row(i) Is Nothing AndAlso Not (row(i) Is DBNull.Value) Then
                    Dim data = Trim(row(i).ToString)
                    listServeurs.Add(data)
                End If
            Next
        End While
        dataReadConnexion.Dispose()
    End Sub

    Public Sub startThreadServeurs()
        threadServeurs = New Thread(AddressOf initTimerServeurs)
        threadServeurs.Start()
    End Sub

    Private Sub initTimerServeurs()
        Try
            timerServeurs = New System.Timers.Timer(sysConfig.iTimerServeurs)
            If (cbStartServeurs <> Nothing) Then
                AddHandler timerServeurs.Elapsed, Sub(sender, e) cbStartServeurs()
            End If
            AddHandler timerServeurs.Elapsed, AddressOf cbTimerServeurs
            If (cbEndServeurs <> Nothing) Then
                AddHandler timerServeurs.Elapsed, Sub(sender, e) cbEndServeurs()
            End If

            If (cbStartServeurs <> Nothing) Then
                cbStartServeurs()
            End If
            cbTimerServeurs(Nothing, Nothing)
            If (cbEndServeurs <> Nothing) Then
                cbEndServeurs()
            End If
        Catch ex As Exception
            Dim err = ex.Message
        End Try
    End Sub

    Private Sub cbTimerServeurs(ByVal source As Object, ByVal e As ElapsedEventArgs)
        timerServeurs.Stop()
        sqlConnexion(1) = New SqlConnection()
        sqlConnexion(1).ConnectionString = sConnexion
        sqlConnexion(1).Open()

        Dim origin As New Date(1970, 1, 1)
        Dim span As TimeSpan = Now - origin
        Dim idPassage As Long = Math.Ceiling(span.TotalSeconds)

        recupererListeServeurs()

        For Each ip As String In listServeurs
            Dim oServeurData As New dataReportServeurs()
            oServeurData.uServeurIP = IPAddress.Parse(ip)
            oServeurData.dVerificationDate = Now
            oServeurData.sVerificationStatut = enStatutVerifications.Aucune
            oServeurData.sMessageErreur = String.Empty
            envoiPing(oServeurData)
            reportServeurs(idPassage, oServeurData)
        Next
        sqlConnexion(1).Dispose()
        sqlConnexion(1).Close()
        timerServeurs.Start()
    End Sub

    Private Sub envoiPing(ByRef oServeurData As dataReportServeurs)
        Try
            Dim ping As Ping = New Ping()
            Dim reponse As PingReply = ping.Send(oServeurData.uServeurIP)
            If Not reponse.Status = IPStatus.Success Then
                oServeurData.sVerificationStatut = enStatutVerifications.ReverificationRequise
                oServeurData.sMessageErreur = reponse.Status.ToString
            End If
        Catch ex As PingException
            oServeurData.sVerificationStatut = enStatutVerifications.ReverificationRequise
            oServeurData.sMessageErreur = ex.Message
        End Try
    End Sub

    Private Sub reportServeurs(ByVal idPassage As Long, ByVal oServeurData As dataReportServeurs)
        Try
            If (Not oServeurData.sMessageErreur = String.Empty) Then
                If (oServeurData.sVerificationStatut = enStatutVerifications.ReverificationRequise) Then
                    oServeurData.iErreurCount = 1
                    If (listErrServeurs.Count = 0) Then
                        listErrServeurs.Add(oServeurData)
                    Else
                        For i = 0 To listErrServeurs.Count - 1 Step 1
                            If (listErrServeurs(i).uServeurIP.ToString = oServeurData.uServeurIP.ToString) Then
                                If (listErrServeurs(i).sMessageErreur = oServeurData.sMessageErreur) Then
                                    oServeurData.iErreurCount = listErrSitesWeb(i).iErreurCount + 1
                                    listErrServeurs(i) = oServeurData
                                End If
                                If (oServeurData.iErreurCount >= sysConfig.iNbErreurServeurs) Then
                                    oServeurData.sVerificationStatut = enStatutVerifications.ErreurMajeur
                                End If
                            ElseIf i = listErrServeurs.Count - 1 Then
                                listErrServeurs.Add(oServeurData)
                            End If
                        Next
                    End If
                End If
            Else
                For i = 0 To listErrServeurs.Count - 1 Step 1
                    If (listErrServeurs(i).uServeurIP.ToString = oServeurData.uServeurIP.ToString) Then
                        listErrServeurs.RemoveAt(i)
                    End If
                Next
            End If

            Dim sRequete = "INSERT INTO Rapport_serveurs VALUES ('" _
                           & oServeurData.uServeurIP.ToString & "', '" _
                           & oServeurData.dVerificationDate.ToString & "', '" _
                           & idPassage.ToString & "', '" _
                           & oServeurData.sVerificationStatut.ToString & "', '" _
                           & Replace(oServeurData.sMessageErreur.ToString, "'", """") & "', " _
                            & oServeurData.iErreurCount & ")"
            scConnexion = New SqlCommand(sRequete, sqlConnexion(1))
            dataConnexion.SelectCommand = scConnexion
            dataConnexion.Fill(dsConnexion)
            dataConnexion.Dispose()
        Catch ex As Exception
            Dim test = ex.Message
        End Try
    End Sub
#End Region

#Region "Web services"
    Private Sub recupererListeWebServices()
        Dim sRequete = "SELECT nom, url, methode FROM Config_services"
        Dim row As Object() = Nothing
        listWebServices.Clear()

        scConnexion = New SqlCommand(sRequete, sqlConnexion(2))
        dataReadConnexion = scConnexion.ExecuteReader

        While dataReadConnexion.Read
            If row Is Nothing Then
                row = New Object(dataReadConnexion.FieldCount) {}
            End If
            dataReadConnexion.GetValues(row)
            Dim webService(2) As String
            webService(0) = Trim(row(0).ToString)
            webService(1) = Trim(row(1).ToString)
            webService(2) = Trim(row(2).ToString)
            listWebServices.Add(webService)
        End While
        dataReadConnexion.Dispose()
    End Sub

    Public Sub startThreadWebServices()
        threadWebServices = New Thread(AddressOf initTimerWebServices)
        threadWebServices.Start()
    End Sub

    Private Sub initTimerWebServices()
        Try
            timerWebServices = New System.Timers.Timer(sysConfig.iTimerServices)
            If (cbStartWebServices <> Nothing) Then
                AddHandler timerWebServices.Elapsed, Sub(sender, e) cbStartWebServices()
            End If
            AddHandler timerWebServices.Elapsed, AddressOf cbTimerWebServices
            If (cbEndWebServices <> Nothing) Then
                AddHandler timerWebServices.Elapsed, Sub(sender, e) cbEndWebServices()
            End If

            If (cbStartWebServices <> Nothing) Then
                cbStartWebServices()
            End If
            cbTimerWebServices(Nothing, Nothing)
            If (cbEndWebServices <> Nothing) Then
                cbEndWebServices()
            End If
        Catch ex As Exception
            Dim err = ex.Message
        End Try
    End Sub

    Private Sub cbTimerWebServices(ByVal source As Object, ByVal e As ElapsedEventArgs)
        timerWebServices.Stop()
        sqlConnexion(2) = New SqlConnection()
        sqlConnexion(2).ConnectionString = sConnexion
        sqlConnexion(2).Open()

        Dim origin As New Date(1970, 1, 1)
        Dim span As TimeSpan = Now - origin
        Dim idPassage As Long = Math.Ceiling(span.TotalSeconds)

        recupererListeWebServices()

        For Each wsInfo As Array In listWebServices
            Dim oServiceData As New dataReportServices()
            oServiceData.uServiceUrl = New Uri(wsInfo(1))
            oServiceData.uServiceName = wsInfo(0)
            oServiceData.uServiceMethode = wsInfo(2)
            oServiceData.dVerificationDate = Now
            oServiceData.sVerificationStatut = enStatutVerifications.Aucune
            oServiceData.sMessageErreur = String.Empty
            verifierWebServices(oServiceData)
            reportWebServices(idPassage, oServiceData)
        Next
        sqlConnexion(2).Dispose()
        sqlConnexion(2).Close()
        timerWebServices.Start()
    End Sub

    Private Sub verifierWebServices(ByRef oServiceData As dataReportServices)
        Try
            Dim WebService As KelDynamicWS = New KelDynamicWS(oServiceData.uServiceUrl)
            Dim resultatWebService = WebService.InvokeMethod(oServiceData.uServiceName, oServiceData.uServiceMethode, Nothing)
            If Not resultatWebService = True Then
                oServiceData.sVerificationStatut = enStatutVerifications.ReverificationRequise
                oServiceData.sMessageErreur = "La méthode à retourné une valeur inattendue"
            End If
        Catch ex As Exception
            oServiceData.sVerificationStatut = enStatutVerifications.ReverificationRequise
            oServiceData.sMessageErreur = ex.Message
        End Try
    End Sub

    Private Sub reportWebServices(ByVal idPassage As Long, ByVal oServiceData As dataReportServices)
        Try
            If (Not oServiceData.sMessageErreur = String.Empty) Then
                If (oServiceData.sVerificationStatut = enStatutVerifications.ReverificationRequise) Then
                    oServiceData.iErreurCount = 1
                    If (listErrWebServices.Count = 0) Then
                        listErrWebServices.Add(oServiceData)
                    Else
                        For i = 0 To listErrWebServices.Count - 1 Step 1
                            If (listErrWebServices(i).uServiceUrl = oServiceData.uServiceUrl) Then
                                If (listErrWebServices(i).sMessageErreur = oServiceData.sMessageErreur) Then
                                    oServiceData.iErreurCount = listErrSitesWeb(i).iErreurCount + 1
                                    listErrWebServices(i) = oServiceData
                                End If
                                If (oServiceData.iErreurCount >= sysConfig.iNbErreurServices) Then
                                    oServiceData.sVerificationStatut = enStatutVerifications.ErreurMajeur
                                End If
                            ElseIf i = listErrWebServices.Count - 1 Then
                                listErrWebServices.Add(oServiceData)
                            End If
                        Next
                    End If
                End If
            Else
                For i = 0 To listErrWebServices.Count - 1 Step 1
                    If (listErrWebServices(i).uServiceUrl Is oServiceData.uServiceUrl) Then
                        listErrWebServices.RemoveAt(i)
                    End If
                Next
            End If

            Dim sRequete = "INSERT INTO Rapport_services VALUES ('" _
                           & oServiceData.uServiceUrl.ToString & "', '" _
                           & oServiceData.uServiceMethode.ToString & "', '" _
                           & oServiceData.dVerificationDate.ToString & "', '" _
                           & idPassage.ToString & "', '" _
                           & oServiceData.sVerificationStatut.ToString & "', '" _
                           & Replace(oServiceData.sMessageErreur.ToString, "'", """") & "', " _
                            & oServiceData.iErreurCount & ")"
            scConnexion = New SqlCommand(sRequete, sqlConnexion(2))
            dataConnexion.SelectCommand = scConnexion
            dataConnexion.Fill(dsConnexion)
            dataConnexion.Dispose()
        Catch ex As Exception
            Dim test = ex.Message
        End Try
    End Sub
#End Region

End Class
